package com.cykj.pos.util;

import com.cykj.pos.domain.BizBehalfPayment;
import com.cykj.pos.pojo.RequestHeadOfOffice3;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class HqyApiUtilsV2 {

    private static RequestConfig requestConfig;

    static {
        // 设置请求和传输超时时间
        requestConfig = RequestConfig
                .custom()
                .setConnectTimeout(15000)
                .setConnectionRequestTimeout(15000)
                .setSocketTimeout(90000)
                .build();
    }

    public static String getMerHead(String function, String merCode,BizBehalfPayment bizBehalfPayment) {
        RequestHead head = new RequestHead();
        head.setFunction(function);
//        if (StringUtils.isBlank(merCode) && StringUtils.isNotBlank(HqyApiContantsV2.HQY_MER_ID_DQHB_V2)) {
        if (StringUtils.isBlank(merCode) && StringUtils.isNotBlank(bizBehalfPayment.getBehalfCode())) {
//            merCode = HqyApiContantsV2.HQY_MER_ID_DQHB_V2;
            merCode = bizBehalfPayment.getBehalfCode();
        }
        head.setMerCode(merCode);
        head.setVersion("2.0");
        head.setReqTime(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date()));
        return JsonUtil.toJsonDefault(head);
    }

    public static Map<String, Object> callHqyMerApi(String logPrefix, String function, Object data, BizBehalfPayment bizBehalfPayment) {
        return callHqyMerApi(logPrefix, function, null, data,bizBehalfPayment);
    }

    public static Map<String, Object> callHqyMerApi(String logPrefix, String function, String merCode, Object data, BizBehalfPayment bizBehalfPayment) {
        boolean success = false;
        String result = null;
        try {
            String srcHead = getMerHead(function, merCode,bizBehalfPayment);
            log.info("{}|reqeust->head:{}", logPrefix, srcHead);
            srcHead = URLEncoder.encode(srcHead, "UTF-8");
            String srcBody = JsonUtil.toJsonDefault(data);
            log.info("{}|reqeust->body:{}", logPrefix, srcBody);
            srcBody = URLEncoder.encode(srcBody, "UTF-8");
            log.info("{}|reqeust->body URLEncoder:{}", logPrefix, srcBody);
//            String aesBody = AESUtilApi.encrypt(srcBody, HqyApiContantsV2.HQY_MER_KEY_V2);
            String aesBody = AESUtilApi.encrypt(srcBody, bizBehalfPayment.getBehalfKey());
            log.info("{}|reqeust->body AES密文:{}", logPrefix, aesBody);
//            String cipher = Md5Util.getMd5(srcHead + "#" + aesBody, HqyApiContantsV2.HQY_MER_KEY_V2, "UTF-8").toUpperCase();
            String cipher = Md5Util.getMd5(srcHead + "#" + aesBody,bizBehalfPayment.getBehalfKey() , "UTF-8").toUpperCase();
            log.info("{}|reqeust->cipher:{}", logPrefix, cipher);
//            String sign = RSAPemCoder.sign(aesBody.getBytes(), RSAPemCoder.getPrivateKeyFromPem(HqyApiContantsV2.HQY_MER_PRIVATE_KEY_PATH_V2));
            String sign = RSAPemCoder.sign(aesBody.getBytes(), RSAPemCoder.getPrivateKeyFromPem(bizBehalfPayment.getBehalfPrivateKey()));
            log.info("{}|reqeust->sign:{}", logPrefix, sign);
            Map<String, String> reqMap = new HashMap<>();
            reqMap.put("reqMsgId", IdGen.uuid());
            reqMap.put("head", srcHead);
            reqMap.put("cipher", cipher);
            reqMap.put("body", aesBody);
            reqMap.put("sign", sign);
            String sendJson = JsonUtil.mapToJson(reqMap);
            log.info("{}|reqeust->sendJson：{}", logPrefix, sendJson);
            HttpClientBuilder builder = HttpClients.custom();
            HttpClient httpClient = builder.build();
            HttpPost httpPost = new HttpPost(HqyApiContantsV2.HQY_MER_API_URL_V2);
            httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.setEntity(new StringEntity(sendJson, Charset.forName("UTF-8")));
            httpPost.setConfig(requestConfig);
            String responseStr = null;
            try {
                HttpResponse httpResponse = httpClient.execute(httpPost);
                if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    responseStr = EntityUtils.toString(httpResponse.getEntity(), "utf-8");
                }
            } catch (Exception e) {
                throw new RuntimeException("post请求提交失败", e);
            } finally {
                httpPost.releaseConnection();
            }
            log.info("{}|repsonse->str:{}", logPrefix, responseStr);
            // 解析
            JSONObject respJsonObj = new JSONObject(responseStr);
            log.info("{}|repsonse->json:{}", logPrefix, respJsonObj.toString());
            String headStr = respJsonObj.getString("head");
            headStr = URLDecoder.decode(headStr, "UTF-8");
            log.info("{}|repsonse->headStr:{}", logPrefix, headStr);
            String cipherStr = respJsonObj.getString("cipher");
            String bodyStr = respJsonObj.getString("body");
            String signStr = respJsonObj.getString("sign");
            String srcResBody = null;
            if (StringUtils.isNotBlank(bodyStr)) {
                headStr = URLEncoder.encode(headStr, "UTF-8");
//                String cipherRes = Md5Util.getMd5(headStr + "#" + bodyStr, HqyApiContantsV2.HQY_MER_KEY_V2, "UTF-8").toUpperCase();
                String cipherRes = Md5Util.getMd5(headStr + "#" + bodyStr, bizBehalfPayment.getBehalfKey(), "UTF-8").toUpperCase();
                log.info("{}|repsonse->cipherRes:{}", logPrefix, cipherRes);
                if (!StringUtils.equalsIgnoreCase(cipherRes, cipherStr)) {
                    throw new RuntimeException("收到的响应cipher验证失败");
                }
                log.info("{}|repsonse->cipher签名成功", logPrefix);
//                if (!RSAPemCoder.verify(bodyStr.getBytes(), RSAPemCoder.getPublicKeyFromPem(HqyApiContantsV2.HQY_MER_PUBLIC_KEY_PATH_V2), signStr)) {
                if (!RSAPemCoder.verify(bodyStr.getBytes(), RSAPemCoder.getPublicKeyFromPem(bizBehalfPayment.getBehalfPublicKey()), signStr)) {
                    throw new RuntimeException("收到的响应：sign签名失败");
                }
                log.info("{}|repsonse->sign签名成功", logPrefix);
//                srcResBody = AESUtilApi.decrypt(bodyStr, HqyApiContantsV2.HQY_MER_KEY_V2);
                srcResBody = AESUtilApi.decrypt(bodyStr, bizBehalfPayment.getBehalfKey());
                log.info("{}|repsonse->srcResBody:{}", logPrefix, srcResBody);
                srcResBody = URLDecoder.decode(srcResBody, "UTF-8");
                log.info("{}|repsonse->明文body:{}", logPrefix, srcResBody);
            }
            result = srcResBody;
            success = true;
        } catch (Exception e) {
            log.error("调用汇企云接口失败", e);
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("code", success ? "S" : "F");
        resultMap.put("result", result);
        return resultMap;
    }


    /*public static Map<String, Object> callHqyOfficeApi(String logPrefix, String function, String merCode, Object data) {
        return callHqyOfficeApi(logPrefix, function, null, merCode, data);
    }

    public static Map<String, Object> callHqyOfficeApi(String logPrefix, String function, String insID, String merCode, Object data) {
        boolean success = false;
        String result = null;
        try {
            String srcHead = getOfficeHead(function, insID, merCode);
            log.info("{}|reqeust->head:{}", logPrefix, srcHead);
            srcHead = URLEncoder.encode(srcHead, "UTF-8");
            String srcBody = JsonUtil.toJsonDefault(data);
            log.info("{}|reqeust->body:{}", logPrefix, srcBody);
            srcBody = URLEncoder.encode(srcBody, "UTF-8");
            log.info("{}|reqeust->body URLEncoder:{}", logPrefix, srcBody);
            String aesBody = AESUtilApi.encrypt(srcBody, HqyApiContantsV2.HQY_MER_KEY_V2);
            log.info("{}|reqeust->body AES密文:{}", logPrefix, aesBody);
            String cipher = Md5Util.getMd5(srcHead + "#" + aesBody, HqyApiContantsV2.HQY_MER_KEY_V2, "UTF-8").toUpperCase();
            log.info("{}|reqeust->cipher:{}", logPrefix, cipher);
            String sign = RSAPemCoder.sign(aesBody.getBytes(), RSAPemCoder.getPrivateKeyFromPem(HqyApiContantsV2.HQY_MER_PRIVATE_KEY_PATH_V2));
            log.info("{}|reqeust->sign:{}", logPrefix, sign);
            Map<String, String> reqMap = new HashMap<String, String>();
            reqMap.put("reqMsgId", IdGen.uuid());
            reqMap.put("head", srcHead);
            reqMap.put("cipher", cipher);
            reqMap.put("body", aesBody);
            reqMap.put("sign", sign);
            String sendJson = JsonUtil.mapToJson(reqMap);
            log.info("{}|reqeust->sendJson:{}", logPrefix, sendJson);
            HttpClientBuilder builder = HttpClients.custom();
            HttpClient httpClient = builder.build();
            HttpPost httpPost = new HttpPost(HqyApiContantsV2.HQY_MER_API_URL_V2);
            httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.setEntity(new StringEntity(sendJson, Charset.forName("UTF-8")));
            httpPost.setConfig(requestConfig);
            String responseStr = null;
            try {
                HttpResponse httpResponse = httpClient.execute(httpPost);
                if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    responseStr = EntityUtils.toString(httpResponse.getEntity(), "utf-8");
                }
            } catch (Exception e) {
                throw new RuntimeException("post请求提交失败", e);
            } finally {
                httpPost.releaseConnection();
            }
            log.info("{}|repsonse->str:{}", logPrefix, responseStr);
            // 解析
            JSONObject respJsonObj = new JSONObject(responseStr);
            log.info("{}|repsonse->json:{}", logPrefix, respJsonObj.toString());
            String headStr = respJsonObj.getString("head");
            headStr = URLDecoder.decode(headStr, "UTF-8");
            String cipherStr = respJsonObj.getString("cipher");
            String bodyStr = respJsonObj.getString("body");
            String signStr = respJsonObj.getString("sign");
            String srcResBody = null;
            if (StringUtils.isNotBlank(bodyStr)) {
                headStr = URLEncoder.encode(headStr, "UTF-8");
                log.info("{}|repsonse->headStr:{}", logPrefix, headStr);
                String cipherRes = Md5Util.getMd5(headStr + "#" + bodyStr, HqyApiContantsV2.HQY_MER_KEY_V2, "UTF-8").toUpperCase();
                log.info("{}|repsonse->cipherRes:{}", logPrefix, cipherRes);
                if (!StringUtils.equalsIgnoreCase(cipherRes, cipherStr)) {
                    throw new RuntimeException("收到的响应cipher验证失败");
                }
                log.info("{}|repsonse->cipher签名成功", logPrefix);
                if (!RSAPemCoder.verify(bodyStr.getBytes(), RSAPemCoder.getPublicKeyFromPem(HqyApiContantsV2.HQY_MER_PUBLIC_KEY_PATH_V2), signStr)) {
                    throw new RuntimeException("收到的响应：sign签名失败");
                }
                log.info("{}|repsonse->sign签名成功", logPrefix);
                srcResBody = AESUtilApi.decrypt(bodyStr, HqyApiContantsV2.HQY_MER_KEY_V2);
                log.info("{}|repsonse->srcResBody:{}", logPrefix, srcResBody);
                srcResBody = URLDecoder.decode(srcResBody, "UTF-8");
                log.info("{}|repsonse->明文body:{}", logPrefix, srcResBody);
            }
            result = srcResBody;
            success = true;
        } catch (Exception e) {
            log.error("调用汇企云接口失败", e);
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("code", success ? "S" : "F");
        resultMap.put("result", result);
        return resultMap;
    }

    private static String getOfficeHead(String function, String merCode) {
        return getOfficeHead(function, null, merCode);
    }

    private static String getOfficeHead(String function, String insID, String merCode) {
        RequestHeadOfOffice3 head = new RequestHeadOfOffice3();
        head.setFunction(function);
        if (StringUtils.isBlank(insID) && StringUtils.isNotBlank(HqyApiContantsV2.HQY_MER_ID_DQHB_V2)) {
            insID = HqyApiContantsV2.HQY_MER_ID_DQHB_V2;
        }
        head.setInsID(insID);
        head.setMer_id(merCode);
        head.setVersion("2.0");
        head.setReqTime(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date()));
        return JsonUtil.toJsonDefault(head);
    }*/

}
